﻿using FySystem.Logs;
using IOT.Services;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IOT
{
    /// <summary>
    /// 长连接类型的IOT
    /// </summary>
    public class IOTLCFactory<T>
    {
        #region 私有变量
        private List<Action<IOTLCFactory<T>>> _jobs1 = new List<Action<IOTLCFactory<T>>>();
        #endregion

        #region 内部用
        internal ArrayPool<byte> BArrayPool = ArrayPool<byte>.Create();
        #endregion

        public delegate void ConnectionGCHandler(IOTStateObject<T> iOTStateObject);

        #region 服务
        /// <summary>
        /// 设备服务
        /// </summary>
        public DeviceService<T> DeviceService { get; private set; }

        #endregion

        #region 回调
        /// <summary>
        /// 当needDeviceService和needDeviceServiceGC都为true时，如果连接断开，则触发该回调
        /// </summary>
        /// <param name="iOTStateObject"></param>
        public ConnectionGCHandler ConnectionGCCallback { get; set; }
        #endregion

        #region 其它属性
        /// <summary>
        /// 数据发送时间间隔，单位毫秒
        /// </summary>
        public int SendDeltaTime { get; set; } = 100;
        /// <summary>
        /// 超时时间，单位秒，默认15s
        /// </summary>
        public int TimeOut { get; set; } = 15;
        #endregion

        /// <summary>
        /// 创建IOT服务
        /// </summary>
        /// <returns></returns>
        public IOTLCFactory()
        {
            try
            {
                DeviceService = new DeviceService<T>();        //初始化
                _jobs1.Add(DeviceService.GC);               //连接释放
                _jobs1.Add(DeviceService.RealSend);         //数据的实际发送管理

                Task task = new Task(InitTimer);
                task.Start();
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 创建消息
        /// </summary>
        /// <param name="needReply"></param>
        /// <param name="package"></param>
        /// <param name="replyHit"></param>
        /// <param name="receiveCallback"></param>
        /// <param name="cdata">用户自定义数据</param>
        /// <returns></returns>
        public IOTMessage<T> CreateIOTMessage(bool needReply, byte[] package, IOTMessage<T>.ReplyHitHandler replyHit = null, IOTMessage<T>.ReceiveHandler receiveCallback = null, object cdata = null)
        {
            try
            {
                return new IOTMessage<T>()
                {
                    NeedReply = needReply,
                    Package = package,
                    ReplyHit = replyHit,
                    ReceiveCallback = receiveCallback,
                    CData = cdata
                };
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 初始化计时器，该计时器用于执行一些内部定时服务
        /// </summary>
        private void InitTimer()
        {
            long deltaTime = 0;
            Stopwatch sw = new Stopwatch();

            while (true)
            {
                if (deltaTime >= 10)
                    Thread.Sleep(0);
                else
                    Thread.Sleep(10 - (int)deltaTime);

                try
                {
                    sw.Restart();
                    foreach (var item in _jobs1)
                        item.Invoke(this);

                    sw.Stop();
                    deltaTime = sw.ElapsedMilliseconds;
                }
                catch(Exception ex)
                {
                    FyLogContextV2.WriteError("InitTimer", ex.Message);
                }
            }
        }
    }
}
